/*Copyright (C) 2009 - 2011 Careil Baptiste

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include "bool.h"
#include "list.h"

/*
Schéma de la liste:
			+<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-+
			|                                                          |
List -+-> structList -+->data                                    |
											+->next -> NULL  (premier de la liste)     |
											+->prev -> structList-+->data              |
																						+->next ->->->->->---+
																						+->prev -> NULL (dernier)
*/

/*
** Permet d'insérer un élément en fin de liste.
*/
void List_PushBack(List *list, int data) {
	structList *newNode = malloc(sizeof(structList));
	newNode->prev = EMPTY_LIST;
	newNode->data = data;

	if(*list != EMPTY_LIST) {
		structList *temp = *list;

		while(temp->prev != EMPTY_LIST) {
			temp = temp->prev;
		}

		temp->prev = newNode;

		newNode->next = temp;
	}
	else {
		*list = newNode;
	}
}

/*
** Permet d'insérer un élément en début de liste.
*/
void List_PushUp(List *list, int data) {
	structList *newNode = malloc(sizeof(structList));
	newNode->next = EMPTY_LIST;
	newNode->prev = *list;
	newNode->data = data;

	if(*list != EMPTY_LIST) {
		(*list)->next = newNode;
	}

	*list = newNode;
}

/*
** Permet d'insérer un élément dans la liste.
*/
void List_Insert(List *list, int data, int index) {
	if(index == 0) {
		List_PushUp(list, data);
	}
	else {
		int i = 0;
		structList *tempPrev, *tempNext;
		structList *newNode = malloc(sizeof(structList));
		newNode->data = data;
		tempNext = *list;

		while(i < index - 1) {
			tempNext = tempNext->prev;
			i++;
		}

		tempPrev = tempNext->prev;

		tempPrev->next = newNode;
		tempNext->prev = newNode;
		newNode->next = tempNext;
		newNode->prev = tempPrev;
	}
}

/*
** Permet de supprimer l'élément en fin de liste.
*/
void List_PopBack(List *list) {
	structList *tempToDel, *tempNewEnd;
	tempToDel = *list;

	if(tempToDel->prev == EMPTY_LIST) {
		List_PopUp(list);
	}
	else {
		while(tempToDel->prev != EMPTY_LIST) {
			tempToDel = tempToDel->prev;
		}

		tempNewEnd = tempToDel->next;

		tempNewEnd->prev = EMPTY_LIST;
		free(tempToDel);
	}
}

/*
** Permet de supprimer l'élément en tête de liste.
*/
void List_PopUp(List *list) {
	structList *temp = *list;

	if(temp->prev == EMPTY_LIST) {
		free(temp);
		*list = EMPTY_LIST;
	}
	else {
		temp = temp->prev;
		free(temp->next);
		temp->next = EMPTY_LIST;
		*list = temp;
	}
}

/*
** Permet de supprimer un élément.
*/
void List_Delete(List *list, int index) {
	if(index == 0) {
		List_PopUp(list);
	}
	else {
		int i = 0;
		structList *tempPrev, *tempNext;
		tempNext = *list;

		while(i < index - 1) {
			tempNext = tempNext->prev;
			i++;
		}

		tempPrev = tempNext->prev->prev;

		free(tempNext->prev);
		tempNext->prev = tempPrev;

		if(tempPrev != EMPTY_LIST) {
			tempPrev->next = tempNext;
		}
	}
}

/*
** Permet de connaitre la taille de la liste.
*/
int List_Size(List list) {
	structList *temp = list;
	int i = 0;

	if(temp != EMPTY_LIST) {
		i++;

		while(temp->prev != EMPTY_LIST) {
			temp = temp->prev;
			i++;
		}
	}

	return i;
}

/*
** Permet de vider la liste de ses éléments.
*/
void List_Clear(List *list) {
	structList *temp = *list;

	if(temp != EMPTY_LIST) {
		while(temp->prev != EMPTY_LIST) {
			temp = temp->prev;
			free(temp->next);
		}

		free(temp);

		*list = EMPTY_LIST;
	}
}

/*
** Permet de récupérer un élément.
*/
int List_Get(List list, int index) {
	int i = 0;
	structList *temp = list;

	while(i < index) {
		temp = temp->prev;
		i++;
	}

	return temp->data;
}

/*
** Permet d'initialiser un élément de la liste
*/
void List_Set(List *list, int data, int index) {
	int i = 0;
	structList *temp = *list;

	while(i < index) {
		temp = temp->prev;
		i++;
	}

	temp->data = data;
}

